;;;; Created on 2007-03-24 22:14:41

;;; STATS

;; Measures the entropy of a list
(defun entropy (lst)
  (let ((total 0) (entropy 0) (counter (make-hash-table :test #'equal :size 16)))
    (dolist (val lst)
      (setf total (+ 1 total))
      (if (gethash val counter)
          (setf (gethash val counter) (+ 1 (gethash val counter)))
          (setf (gethash val counter) 1)))
    (with-hash-table-iterator (counter-it counter)
      (loop
        (multiple-value-bind (entry-p key value)
          (counter-it)
          (if entry-p
              (if (not (or (equal (hash-table-count counter) 1) (equal (hash-table-count counter) 0)))
                  (setf entropy (- entropy (* (/ value total) (log (/ value total) (hash-table-count counter))))))
              (return)))))
    entropy))

;; Measures the entropy of a for a 2-dimensional list element
(defun nth-entropy (data pred)
  (let ((vals nil))
    (dolist (val data)
      (setf vals (cons (nth pred val) vals)))
    (entropy vals)))

(defun sum (lst)
  (let ((total 0))
    (progn
      (dolist (val lst)
          (if (numberp val)
            (setf total (+ val total))))
      total)))

(defun mean (lst)
  (/ (sum lst) (length lst)))

(defun nth-mean (lst val)
  (mean (nth val (invert-list lst))))

(defun stddev (lst)
  (let ((m (mean lst)) (dev 0))
    (progn
      (dolist (val lst)
        (if (numberp val)
          (setf dev (+ dev (abs (- val m))))))
      (/ dev (length lst)))))

(defun variance (lst)
  (let ((m (mean lst)) (dev 0))
    (progn
      (dolist (val lst)
        (if (numberp val)
          (setf dev (+ dev (expt (- val m) 2)))))
      (/ dev (length lst)))))


(defun stddev-list (lst)
  (let ((devs nil))
    (progn
      (dolist (cur lst)
        (setf devs (cons (stddev cur) devs)))
      (reverse devs))))